package com.ifacebox.arcsoft.face;

import com.arcsoft.face.ActiveFileInfo;
import com.arcsoft.face.EngineConfiguration;
import org.apache.commons.pool2.*;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author znn
 */
public class ArcSoftFaceEnginePool implements AutoCloseable {
    private static final Logger logger = LoggerFactory.getLogger(ArcSoftFaceEnginePool.class);
    private final ObjectPool<ArcSoftFaceEngine> objectPool;
    private final String libPath, appId, sdkKey;
    private final EngineConfiguration engineConfiguration;

    public ArcSoftFaceEnginePool(String libPath, String appId, String sdkKey, EngineConfiguration engineConfiguration
            , GenericObjectPoolConfig<ArcSoftFaceEngine> objectPoolConfig) {
        this.libPath = libPath;
        this.appId = appId;
        this.sdkKey = sdkKey;
        this.engineConfiguration = engineConfiguration;
        this.objectPool = new GenericObjectPool<>(pooledObjectFactory, objectPoolConfig);
    }

    public void addObjects(int count) throws Exception {
        objectPool.addObjects(count);
    }

    public ArcSoftFaceEngine getFaceEngine() throws Exception {
        return objectPool.borrowObject();
    }

    @Override
    public void close() {
        objectPool.close();
    }

    @Override
    public String toString() {
        return String.format(" ==> NumActive: %s NumIdle: %s ", objectPool.getNumActive(), objectPool.getNumIdle());
    }

    PooledObjectFactory<ArcSoftFaceEngine> pooledObjectFactory = new BasePooledObjectFactory<ArcSoftFaceEngine>() {
        @Override
        public ArcSoftFaceEngine create() throws Exception {
            ArcSoftFaceEngine faceEngine = new ArcSoftFaceEngine(libPath, objectPool);
            ActiveFileInfo activeFileInfo = faceEngine.create(appId, sdkKey, engineConfiguration);
            if (logger.isInfoEnabled()) {
                logger.info("{}\t{} for {} by v{} and v{} expires ({} ~ {})", faceEngine.hashCode()
                        , activeFileInfo.getSdkType(), activeFileInfo.getPlatform()
                        , activeFileInfo.getSdkVersion(), activeFileInfo.getFileVersion()
                        , new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(Long.parseLong(activeFileInfo.getStartTime()) * 1000))
                        , new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(Long.parseLong(activeFileInfo.getEndTime()) * 1000)));
            }
            return faceEngine;
        }

        @Override
        public PooledObject<ArcSoftFaceEngine> wrap(ArcSoftFaceEngine faceEngine) {
            return new DefaultPooledObject<>(faceEngine);
        }

        @Override
        public void destroyObject(PooledObject<ArcSoftFaceEngine> pooledObject, DestroyMode destroyMode) throws Exception {
            ArcSoftFaceEngine faceEngine = pooledObject.getObject();
            faceEngine.destroy();
        }
    };

}
